package main

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"log"
)

// 结构体表示命令信息
type CommandInfo struct {
	SOI    byte   // 开始标志 0x7E
	VER    byte   // 协议版本号
	ADR    byte   // 设备地址
	CID1   byte   // 控制标识 0x60
	CID2   byte   // 命令类型 0x82（获取机组状态）
	LENGTH uint16 // 数据长度
	CHKSUM uint16 // 校验和
	EOI    byte   // 结束标志 0x0D
}

// 机组状态信息结构体
type UnitStatus struct {
	AirConditioningStatus  byte // 空调开关机状态
	FanStatus              byte // 风机输出开关状态
	HumidifierStatus       byte // 加湿器输出开关状态
	Compressor1Status      byte // 压缩机1输出开关状态
	Compressor2Status      byte // 压缩机2输出开关状态
	Heater1Status          byte // 电加热1输出开关状态
	Heater2Status          byte // 电加热2输出开关状态
	CommonAlarmStatus      byte // 公共报警输出开关状态
	LiquidValve1Status     byte // 液路电磁阀1输出开关状态
	LiquidValve2Status     byte // 液路电磁阀2输出开关状态
	HumidifierWaterStatus  byte // 加湿器注水输出开关状态
	DehumidifierStatus     byte // 除湿输出开关状态
	Reserved               byte // 保留
	BackupSwitchStatus     byte // 备用开关（压缩机1反相输出开关状态）
	FanValveSwitchStatus  byte // 风阀开关（压缩机2反相输出开关状态）
	CoolingStatus          byte // 制冷状态
	HeatingStatus          byte // 加热状态
	DehumidifyingStatus    byte // 除湿状态
	HumidifyingStatus      byte // 加湿状态
}

// 计算校验和
func calculateChecksum(data []byte) uint16 {
	var checksum uint16
	for _, b := range data {
		checksum += uint16(b)
	}
	checksum = (checksum & 0xFFFF) ^ 0xFFFF
	checksum++
	return checksum
}

// 构造获取机组状态命令
func buildGetUnitStatusCommand(adr byte) []byte {
	// 创建命令结构体
	command := CommandInfo{
		SOI:    0x7E,           // 开始标志
		VER:    0x21,           // 协议版本号
		ADR:    adr,            // 设备地址
		CID1:   0x60,           // 控制标识
		CID2:   0x82,           // 命令类型
		LENGTH: 0x00,           // 数据长度（命令无数据）
		CHKSUM: 0x00,           // 初始校验和（待计算）
		EOI:    0x0D,           // 结束标志
	}

	// 构建命令数据（排除SOI和EOI）
	cmdData := []byte{
		command.VER,
		command.ADR,
		command.CID1,
		command.CID2,
		byte(command.LENGTH >> 8), // LENGTH 高字节
		byte(command.LENGTH & 0xFF), // LENGTH 低字节
	}

	// 计算校验和
	command.CHKSUM = calculateChecksum(cmdData)

	// 合并所有数据并返回完整命令
	cmdData = append([]byte{command.SOI}, cmdData...)
	cmdData = append(cmdData, byte(command.CHKSUM>>8), byte(command.CHKSUM&0xFF), command.EOI)

	return cmdData
}

// 解析机组状态响应数据
func parseUnitStatusResponse(response []byte) (UnitStatus, error) {
	// 确保响应数据长度正确
	if len(response) < 38 {
		return UnitStatus{}, fmt.Errorf("响应数据长度不足")
	}

	// 提取机组状态信息
	unitStatus := UnitStatus{
		AirConditioningStatus: response[6],   // 空调开关机状态
		FanStatus:             response[7],   // 风机输出开关状态
		HumidifierStatus:      response[8],   // 加湿器输出开关状态
		Compressor1Status:     response[9],   // 压缩机1输出开关状态
		Compressor2Status:     response[10],  // 压缩机2输出开关状态
		Heater1Status:         response[11],  // 电加热1输出开关状态
		Heater2Status:         response[12],  // 电加热2输出开关状态
		CommonAlarmStatus:     response[13],  // 公共报警输出开关状态
		LiquidValve1Status:    response[14],  // 液路电磁阀1输出开关状态
		LiquidValve2Status:    response[15],  // 液路电磁阀2输出开关状态
		HumidifierWaterStatus: response[16],  // 加湿器注水输出开关状态
		DehumidifierStatus:    response[17],  // 除湿输出开关状态
		Reserved:              response[18],  // 保留
		BackupSwitchStatus:    response[19],  // 备用开关状态
		FanValveSwitchStatus: response[20],  // 风阀开关状态
		CoolingStatus:         response[21],  // 制冷状态
		HeatingStatus:         response[22],  // 加热状态
		DehumidifyingStatus:   response[23],  // 除湿状态
		HumidifyingStatus:     response[24],  // 加湿状态
	}

	return unitStatus, nil
}

func main() {
	// 假设设备地址为1
	adr := byte(1)

	// 构造获取机组状态命令
	cmd := buildGetUnitStatusCommand(adr)

	// 打印命令的十六进制表示
	fmt.Println("构造的命令:", hex.EncodeToString(cmd))

	// 假设收到的响应数据（示例数据）
	response := []byte{
		0x7E, 0x21, 0x01, 0x60, 0x82, 0x00, 0x00, 0x00, 0x01, 0x00,
		0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
		0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
		0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0D,
	}

	// 解析响应数据
	unitStatus, err := parseUnitStatusResponse(response)
	if err != nil {
		log.Fatalf("解析响应失败: %v", err)
	}

	// 打印解析后的机组状态
	fmt.Printf("机组状态: %+v\n", unitStatus)
}
